scrapy 中的 xpath 语法与调试

scrapy 中的 xpath 语法与调试

把setting中的机器人过滤设为False

ROBOTSTXT_OBEY = False

1 语法

artcile

选取所有子节点

/article

选取根元素 artile

article/a

选取所有属于artile的子元素中的a元素

//div

选取所有 div 元素(不管出现在文档任何位置)

article//div

选取所有属于artile元素的后代的 div 元素,不管出现在 article 之下的任何位置

//@class

选取所有名为 class 的属性。

/article/div[1]

选取属于article子元素的第一个div元素

/article/div[last()]

选取属于article子元素的最后一个div元素

/article/div[last()-1]

选取属于article子元素的倒数第二个div元素

//div[@lang]

选取所有拥有lang属性的div元素

//div[@lang='eng']

选取所有lang属性为eng的div元素

debug

1 pycharm

id是全局唯一的

re_selector2 = response.xpath('//*[@id="post-110595"]/div[1]/h1/text()')

如果class='entry-header'是全局唯一,可以比上面少一层节点。

re_selector3 = response.xpath("//div[@class='entry-header']/h1/text()")

2 scrapy shell

对某一页http://blog.jobbole.com/110595/ 进行debug

scrapy shell http://blog.jobbole.com/110595/

得到response对象。

可以用dir(response)看属性和方法。用type(response)看类型。

>>> title = response.xpath("//div[@class='entry-header']/h1/text()")
>>> title
[<Selector xpath="//div[@class='entry-header']/h1/text()" data='为什么该和程序员约会?我有 20 个理由'>]

如何获取title中的数据?使用extract()方法,得到数组,再用序号可以得到具体值。

>>> title.extract()
['为什么该和程序员约会?我有 20 个理由']
>>> title.extract()[0]
'为什么该和程序员约会?我有 20 个理由'

不直接extra()是因为title 可以保持为selector对象。

获取时间,把里面的文本用text()获取出来。再用strip()默认出去默认字符。

参考删除字符串中不需要的字符

>>> create_date = response.xpath("//p[@class='entry-meta-hide-on-mobile']/text()").extract()[0]
>>> create_date
'\r\n\r\n            2017/03/18 ·  '
>>> create_date = create_date.strip()
>>> create_date
'2017/03/18 ·'
>>> a = create_date.replace("·","").strip()
>>> a
'2017/03/18'
>>> b = create_date.strip("·")
>>> b
'2017/03/18 '
>>> b = create_date.strip("·").strip()
>>> b
'2017/03/18'

只取多个class属性中的一个,用xpath的函数 contains。

比如要选取span,但是class有多项。而只想要其中的vote-post-up,可以用xpath的contains。

<span data-post-id="110595" class=" btn-bluet-bigger href-style vote-post-up   register-user-only "><i class="fa  fa-thumbs-o-up"></i> <h10 id="110595votetotal">2</h10> 赞</span>
>>> response.xpath("//span[contains(@class, 'vote-post-up')]")
[<Selector xpath="//span[contains(@class, 'vote-post-up')]" data='<span data-post-id="110595" class=" btn-'>]

列表生成式

过滤评论

>>> response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()[0:]
['其他', ' 7 评论 ', '约会']
>>> [element for element in tag_list if not element.strip().endswith("评论")]
['其他', '约会']
tag_list = [ element for element in tag_list if not element.strip().endswith("评论") ]
tags = ",".join(tag_list)

以什么结尾一定是 .endswith()

extract_first()

对数组取第0个、第1个的时候,如果数组为空,则可能抛出异常。

但是如果用extract_first(),不用做异常处理,结果为空或者None。

def extract_first(self, default=None):
    for x in self:
        return x.extract()
    else:
        return default

类似于字典的get方法,提取不到就返回空。

最终 jobbole.py

# -*- coding: utf-8 -*-
import re
import scrapy


class JobboleSpider(scrapy.Spider):
    name = "jobbole"
    allowed_domains = ["blog.jobbole.com"]
    start_urls = ['http://blog.jobbole.com/110595/']

    def parse(self, response):
        # re_selector1 = response.xpath("/html/body/div[1]/div[3]/div[1]/div[1]/h1")
        # re_selector2 = response.xpath('//*[@id="post-110595"]/div[1]/h1/text()')
        # re_selector3 = response.xpath("//div[@class='entry-header']/h1/text()")
        title  = response.xpath("//div[@class='entry-header']/h1/text()").extract()[0]
        create_date = response.xpath("//p[@class='entry-meta-hide-on-mobile']/text()").extract()[0].strip().replace("·","").strip()
        praise_nums = response.xpath("//span[contains(@class, 'vote-post-up')]//h10/text()").extract()[0]
        fav_nums = response.xpath("//span[contains(@class, 'bookmark-btn')]/text()").extract()[0]
        match_re = re.match(".*?(\d+).*", fav_nums)
        if match_re:
            fav_nums = match_re.group(1)
        comment_nums = response.xpath("//a[@href='#article-comment']/span/text()").extract()[0]
        match_re = re.match(".*?(\d+).*", comment_nums)
        if match_re:
            comment_nums = match_re.group(1)

        content = response.xpath("//div[@class='entry']").extract()[0]
        tag_list = response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()
        tag_list = [ element for element in tag_list if not element.strip().endswith("评论") ]
        tags = ",".join(tag_list)


        # 通过css选择器提取字段
        title = response.css(".entry-header h1::text").extract()[0]
        create_date = response.css(".entry-meta-hide-on-mobile::text").extract()[0].strip().replace("·","").strip()
        praise_nums = response.css("div.post-adds h10::text").extract()[0]

        # fav_nums = response.css("span[class*='bookmark-btn']::text").extract()[0]
        fav_nums = response.css(".bookmark-btn::text").extract()[0]
        match_re = re.match(".*?(\d+).*", fav_nums)
        if match_re:
            fav_nums = match_re.group(1)

        # comment_nums = response.css("span[class='btn-bluet-bigger href-style hide-on-480']::text").extract()[0]
        comment_nums = response.css("a[href='#article-comment'] span::text").extract_first()
        match_re = re.match(".*?(\d+).*", comment_nums)
        if match_re:
            comment_nums = match_re.group(1)
        content = response.css(".entry").extract()[0]
        tag_list = response.css("p.entry-meta-hide-on-mobile a::text").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("评论")]
        tags = ",".join(tag_list)
        pass

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容